#ifndef unigame_Pool_h
#define unigame_Pool_h

#include <vector>
#include "config/Def.h"
#include "config/EngineCon.h"
#include "LinkList.h"

namespace unigame
{
	template <class T>
	class Pool
	{
	public:
		Pool(int32u len = 0):m_free(false), m_used(false)
		{
			reset(len);			
		}

		~Pool()
		{
			m_free.clear(false);
			m_used.clear(false);
			for(int32u i = 0, size = m_members.size(); i < size; ++i)
			{
				delete[] m_members[i];
			}
			m_members.clear();
		}

		void clear()
		{
			m_length = 0;
			m_free.append(m_used);
		}

		void reset(int32u len = 0)
		{
			resize(len);
			m_length = 0;
			for(int32u i = 0, size = m_members.size(); i < size; ++i)
			{
				for(int32u j = 0; j < POOL_STEP; ++j)
				{
					m_free.addLast(&m_members[i][j]);
				}
			}
			m_used.clear(false);
		}

		int32u maxSize()
		{
			return m_maxSize;
		}

		int32u length()
		{
			return m_length;
		}

		LinkListItem<T>* addItem()
		{
			++m_length;
			if(m_length > m_maxSize)
			{
				resize(m_length);
				for(int32u i = 0, index = m_members.size() - 1; i < POOL_STEP; ++i)
				{
					m_free.addLast(&m_members[index][i]);
				}
			}
			LinkListItem<T>* temp = m_free.removeFirst();
			m_used.addLast(temp);
			return temp;
		}

		void removeItem(LinkListItem<T>* item)
		{
			if(m_length > 0)
			{
				--m_length;
				LinkListItem<T>* temp = m_used.remove(item);
				m_free.addFirst(temp);
			}
		}

	private:
		void resize(int32u len)
		{
			int32u l = len % POOL_STEP;
			if(l == 0)
			{
				l = len / POOL_STEP;
			}
			else
			{
				l = len / POOL_STEP + 1;
			}
			if(l > (int)m_members.size())
			{
				for(int32u i = l - m_members.size(); i > 0; --i)
				{
					m_members.push_back(uni_new LinkListItem<T>[POOL_STEP]);
				}
			}
			else if(l < (int)m_members.size())
			{
				for(int32u i = m_members.size() - l; i > 0; --i)
				{
					LinkListItem<T>* p = m_members[m_members.size() - 1];
					m_members.pop_back();
					delete[] p;
				}
			}
			m_maxSize = m_members.size() * POOL_STEP;
		}

	private:
		std::vector<LinkListItem<T>*> m_members;
		LinkList<T> m_free;
		LinkList<T> m_used;
		int32u m_length;
		int32u m_maxSize;
	};
}

#endif